home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / ge_cool.lha / GE_COOL2.1 / src / Complex / Complex.h < prev    next >
C/C++ Source or Header  |  1992-07-14  |  17KB  |  464 lines

  1. //
  2. // Copyright (C) 1991 Texas Instruments Incorporated.
  3. // Copyright (C) 1992 General Electric Company.
  4. //
  5. // Permission is granted to any individual or institution to use, copy, modify,
  6. // and distribute this software, provided that this complete copyright and
  7. // permission notice is maintained, intact, in all copies and supporting
  8. // documentation.
  9. //
  10. // Texas Instruments Incorporated and General Electric Company
  11. // provides this software "as is" without express or implied warranty.
  12. //
  13. //
  14. // Created: MBN 10/25/89 -- Initial design and implementation
  15. // Updated: MBN 03/04/90 -- Added execption for DIVIDE_BY_ZERO
  16. // Updated: MJF 07/31/90 -- Added terse print
  17. // Updated: DLS 03/22/91 -- New lite version
  18. // Updated: VDN 06/29/92 -- roots of real polynomial, degree <= 4.
  19. // 
  20. // The Complex  class implements  Complex  numbers  and arithmetic.   A Complex
  21. // object has the same  precision and range of  values  as  the system built-in
  22. // type double.  Implicit conversion  to  the  system defined types short, int,
  23. // long, float,    and  double   is supported by   overloaded  operator  member
  24. // functions.  Although   the  Complex class  makes   judicous use   of  inline
  25. // functions and deals only with floating point values, the user is warned that
  26. // the Complex double arithmetic class is still  slower than  the built-in real
  27. // data types.
  28. //
  29. // The Complex   class implements common   arithmetic   exception  handling and
  30. // provides  the  application  with support  for   detecting negative infinity,
  31. // positive  infinity, overflow, and underflow as  a  result of some arithmetic
  32. // expression. If one  of these conditions  or  an attempt   to  convert from a
  33. // Complex with no value to a built-in type is detected,  an Error exception is
  34. // raised. The application programmer can provide an exception handler  to take
  35. // care of this problem. If no  such handler is  available, an error message is
  36. // printed and the application terminates.
  37. //
  38. // The Complex class requires several constants be defined to insure precision
  39. // and accuracy   of conversion.  The   preprocessor  symbols MINSHORT, MININT,
  40. // MINLONG, MAXSHORT, MAXINT, and MAXLONG  are calculated  in the <COOL/misc.h>
  41. // header file  via various  bit  manipulation  macros. The  symbols  MINFLOAT,
  42. // MINDOUBLE,  MAXFLOAT,  and MAXDOUBLE  are  system dependent  and cannot   be
  43. // calculated.  Most systems typically have  values  for these constants in the
  44. // system header  file <values.h>.  Values  for a  specific  machine should  be
  45. // copied into the <cool/misc.h> header file as necessary.
  46. //
  47. // The private data section of the Complex class contains two double  data type
  48. // slots,  one for  the real portion  and one for the  imaginary portion.   The
  49. // Complex  class  also contains   a   private  data slot  providing arithmetic
  50. // exception status.  There are four constructors for the  Complex class.   The
  51. // first is a simple inline constructor that  initializes the state and private
  52. // data slots.  The second  takes two integers (short, int,  or long)  and uses
  53. // them  as the initial value for  the object. The  second argument is optional
  54. // and if not supplied, defaults to zero.  The third takes  two reals (float or
  55. // double) and uses  them as  the  initial  value for  the object.  The  second
  56. // argument is optional  and  if not supplied, defaults  to zero.  Finally, the
  57. // fourth takes a const reference to another Complex object and  duplicates its
  58. // state and value.
  59. //
  60. // The Complex  class provides overloaded  operators for addition, subtraction,
  61. // multiplication,  division,  cosine, sine,  hyperbolic cosine  and hyperbolic
  62. // sine.  Also available are  inequality  and equality,  assignment, increment,
  63. // decrement, unary minus, and  output.  Methods to get  the real and imaginary
  64. // part are supported.  Finally,  five virtual operator conversion functions to
  65. // short, int, long, float, and double are provided.
  66. //
  67. // Find roots of a real polynomial in a single variable, with degree <=4.
  68. // Reference: Winston, P.H, Horn, B.K.P. (1984) "Lisp", Addison-Wesley.
  69.  
  70.  
  71. #ifndef COMPLEXH                // If no Complex definition
  72. #define COMPLEXH                // define the Complex symbol
  73.  
  74. #ifndef MATHH
  75. #if defined(DOS)
  76. extern "C" {
  77. #include <math.h>        // include the standard math library
  78. }
  79. #else
  80. #include <math.h>        // include the standard math library
  81. #endif
  82. #define MATHH
  83. #endif
  84.  
  85. #ifndef STREAMH            // If the Stream support not yet defined,
  86. #if defined(DOS) || defined(M_XENIX)
  87. #include <stream.hxx>        // include the Stream class header file
  88. #else
  89. #include <stream.h>        // include the Stream class header file
  90. #endif
  91. #define STREAMH
  92. #endif
  93.  
  94. #ifndef MISCELANEOUSH            // If no misc.h file
  95. #include <misc.h>            // Include useful defintions
  96. #endif    
  97.  
  98. double curt (double d);                // cubic root of a double
  99.  
  100. class CoolComplex {
  101. public:
  102.   inline CoolComplex (double real = 0, double imag = 0); // from real&imaginary
  103.   inline CoolComplex (const CoolComplex&);    // Copy constructor
  104.   inline ~CoolComplex();            // Destructor
  105.  
  106.   inline double real () const;            // Get the numerator
  107.   inline double imaginary () const;        // Get the denominator
  108.   inline N_status status () const;        // Return Number status
  109.  
  110.   inline double modulus () const;        // magnitude or norm of vector
  111.   inline double argument () const;        // angle of vector with x-axis
  112.   
  113.   CoolComplex& operator= (const CoolComplex&);        // Overload assignment
  114.   inline Boolean operator== (const CoolComplex&) const; // Overload equality
  115.   inline Boolean operator!= (const CoolComplex&) const; // Overload inequality
  116.  
  117.   inline CoolComplex invert () const;        // Return reciprical of CoolComplex
  118.   inline CoolComplex operator-() const;        // Unary minus operator
  119.   inline CoolComplex conjugate () const;    // Conjugate of complex number
  120.   inline Boolean operator!() const;        // Logical NOT operator
  121.  
  122.   inline friend CoolComplex operator+ (const CoolComplex&, const CoolComplex&);
  123.   inline friend CoolComplex operator- (const CoolComplex&, const CoolComplex&);
  124.   inline friend CoolComplex operator* (const CoolComplex&, const CoolComplex&);
  125.   inline friend CoolComplex operator/ (const CoolComplex&, const CoolComplex&);     
  126.  
  127.   inline CoolComplex& operator+= (const CoolComplex&);    // Overload add/assigne
  128.   inline CoolComplex& operator-= (const CoolComplex&);    // Overload subtract/assigne
  129.   inline CoolComplex& operator*= (const CoolComplex&);    // Overload multi/assigne
  130.   CoolComplex& operator/= (const CoolComplex&);        // Overload divide/assigne
  131.  
  132.   inline CoolComplex& operator++ ();        // Overload increment
  133.   inline CoolComplex& operator-- ();        // Overload decrement
  134.  
  135.   friend ostream& operator<< (ostream&, const CoolComplex&); 
  136.   inline friend ostream& operator<< (ostream&, const CoolComplex*);
  137.  
  138.   void print(ostream&);                // terse print
  139.  
  140.   inline CoolComplex cos () const;        // Cosine of a complex 
  141.   inline CoolComplex sin () const;        // Sine of a complex
  142.   inline CoolComplex tan () const;        // Tangent of a complex
  143.   inline CoolComplex cosh () const;        // Hyperbolic cosine of complex
  144.   inline CoolComplex sinh () const;        // Hyperbolic sine of complex
  145.   inline CoolComplex tanh () const;        // Hyperbolic tangent
  146.   
  147.   operator short ();                // Virtual implicit conversion
  148.   operator int ();                // Virtual implicit conversion
  149.   operator long ();                // Virtual implicit conversion
  150.   operator float ();                // Virtual implicit conversion
  151.   operator double ();                // Virtual implicit conversion
  152.  
  153.  
  154.   // finding roots of a polynomial in one variable with degree <= 4.
  155.   static int roots_of_linear (const double& a, const double& b, 
  156.                   CoolComplex& r);
  157.  
  158.   static int roots_of_quadratic (const double& a, const double& b, const double& c, 
  159.                  CoolComplex& r1, CoolComplex& r2);
  160.  
  161.   static int roots_of_cubic (const double& a, const double& b, 
  162.                  const double& c, const double& d,
  163.                  CoolComplex& r1, CoolComplex& r2, CoolComplex& r3);
  164.  
  165.   static int roots_of_quartic (const double& a, const double& b, 
  166.                    const double& c, const double& d, const double& e, 
  167.                    CoolComplex& r1, CoolComplex& r2, 
  168.                    CoolComplex& r3, CoolComplex& r4);
  169.  
  170. protected:
  171.   void minus_infinity (const char*) const;    // Raise - infinity exception
  172.   void plus_infinity (const char*) const;    // Raise + infinity exception
  173.   void overflow (const char*) const;        // Raise overflow error
  174.   void underflow (const char*) const;        // Raise overflow error
  175.   void no_conversion (const char*) const;    // Raise no conversion error
  176.   void divide_by_zero (const char*) const;    // Raise divide by zero
  177.  
  178. private:
  179.   double r;                    // Real portion
  180.   double i;                    // Imaginary portion
  181.   N_status state;                // Exception status
  182. };
  183.  
  184.  
  185. // CoolComplex -- Constructor that takes a floating point real part and optional
  186. //            floating point imaginary part to make a complex number
  187. // Input:     Double for real part, optional double for imaginary part
  188. // Output:    None
  189.  
  190. inline CoolComplex::CoolComplex (double rp, double ip) {
  191.   this->r = rp;                    // Set real part
  192.   this->i = ip;                    // Set imaginary part
  193.   this->state = N_OK;                // Set status to OK
  194. }
  195.  
  196.  
  197. // CoolComplex -- Copy constructor
  198. // Input:     Reference to CoolComplex object
  199. // Output:    None
  200.  
  201. inline CoolComplex::CoolComplex (const CoolComplex& c) {
  202.   this->r = c.r;                // Copy real part
  203.   this->i = c.i;                // Copy imaginary part
  204.   this->state = c.state;            // Copy state
  205. }
  206.  
  207. // ~CoolComplex -- Destructor does nothing
  208. // Input:     None
  209. // Output:    None
  210.  
  211. inline CoolComplex::~CoolComplex() {}        // Nothing.
  212.  
  213.  
  214. // real -- Return the real portion of the CoolComplex
  215. // Input:  None
  216. // Output: Real part of CoolComplex
  217.  
  218. inline double CoolComplex::real () const {
  219.   return this->r;                // Return real part
  220. }
  221.  
  222.  
  223. // imaginary -- Return the imaginary portion of the CoolComplex
  224. // Input:       None
  225. // Output:      Imaginary part of CoolComplex
  226.  
  227. inline double CoolComplex::imaginary () const {
  228.   return this->i;                // Return imaginary part
  229. }
  230.  
  231.  
  232. // status -- Return the status of Number
  233. // Input:    None
  234. // Output:   N_status enum value
  235.  
  236. inline N_status CoolComplex::status () const {
  237.   return this->state;
  238. }
  239.  
  240.  
  241. // modulus -- Return the magnitude or norm of Complex vector
  242.  
  243. inline double CoolComplex::modulus () const {
  244.   return sqrt((this->r * this->r) + (this->i * this->i));
  245. }
  246.  
  247. // argument -- Return the angle from x-axis to Complex vector
  248.  
  249. inline double CoolComplex::argument () const {
  250.   return atan2(this->i, this->r);
  251. }
  252.  
  253.  
  254. // operator== -- Overload the equality operator for the CoolComplex class
  255. // Input:        Reference to CoolComplex object
  256. // Output:       TRUE/FALSE
  257.  
  258. inline Boolean CoolComplex::operator== (const CoolComplex& c) const {
  259.   return (this->r == c.r && this->i == c.i);
  260. }
  261.  
  262.  
  263. // operator!= -- Overload the inequality operator for the CoolComplex class
  264. // Input:        Reference to a constant CoolComplex object
  265. // Ouput:        TRUE/FALSE
  266.  
  267. inline Boolean CoolComplex::operator!= (const CoolComplex& c) const {
  268.   return !(*this == c);
  269. }
  270.  
  271.  
  272. // operator<< -- Overload the output operator for a pointer to a CoolComplex
  273. // Input:        Ostream reference, pointer to a CoolComplex object
  274. // Output:       Ostream reference
  275.  
  276. inline ostream& operator<< (ostream& os, const CoolComplex* c) {
  277.   return operator<< (os, *c);
  278. }
  279.  
  280.  
  281. // invert -- Calculate the reciprical of a complex number
  282. // Input:    None
  283. // Output:   Reciprical of complex
  284.  
  285. inline CoolComplex CoolComplex::invert () const {
  286.   double normalize = (this->r * this->r)+(this->i * this->i);
  287.   return CoolComplex ((this->r / normalize), (-this->i / normalize));
  288. }
  289.  
  290.  
  291. // operator- -- Overload the unary minus operator for the CoolComplex class
  292. // Input:       None
  293. // Output:      Negated CoolComplex value
  294.  
  295. inline CoolComplex CoolComplex::operator- () const {
  296.   return CoolComplex (-this->r, -this->i);        // Get negative value
  297. }
  298.  
  299.  
  300. // conjugate -- Provide conjugate (that is, negate imaginary part) of complex
  301. // Input:       None
  302. // Output:      Negated CoolComplex value
  303.  
  304. inline CoolComplex CoolComplex::conjugate () const {
  305.   return CoolComplex (this->r, -this->i);        // Get negative value
  306. }
  307.  
  308.  
  309. // operator! -- Overload the negation operator for the CoolComplex class
  310. // Input:       None
  311. // Output:      TRUE/FALSE
  312.  
  313. inline Boolean CoolComplex::operator! () const {
  314.   return ((this->r == 0.0) ? TRUE : FALSE);    // Return logical state
  315. }
  316.  
  317.  
  318. // operator++ -- Overload the increment operator for the CoolComplex class
  319. // Input:        None
  320. // Output:       Reference to updated CoolComplex object
  321.  
  322. inline CoolComplex& CoolComplex::operator++ () {
  323.   this->r++ ;                    // Increment real part
  324.   return *this;                    // Return updated object
  325. }
  326.   
  327.  
  328. // operator-- -- Overload the decrement operator for the CoolComplex class
  329. // Input:        None
  330. // Output:       Reference to updated CoolComplex object
  331.  
  332. inline CoolComplex& CoolComplex::operator-- () {
  333.   this->r--;                    // Decrement real part
  334.   return *this;                    // Return updated object
  335. }
  336.  
  337.  
  338. // operator+ -- Overload the addition operator for the CoolComplex class
  339. // Input:       Reference to complex object
  340. // Output:      Reference to new complex object
  341.  
  342. inline CoolComplex operator+ (const CoolComplex& c1, const CoolComplex& c2) {
  343.   return CoolComplex (c1.real()+c2.real(), c1.imaginary()+c2.imaginary());
  344. }
  345.  
  346.  
  347. // operator- -- Overload the subtraction operator for the CoolComplex class
  348. // Input:       Reference to CoolComplex object
  349. // Output:      Reference to new CoolComplex object
  350.  
  351. inline CoolComplex operator- (const CoolComplex& c1, const CoolComplex& c2) {
  352.   return CoolComplex (c1.real()-c2.real(), c1.imaginary()-c2.imaginary());
  353. }
  354.  
  355.  
  356. // operator* -- Overload the multiplication operator for the CoolComplex class
  357. // Input:       Reference to complex object
  358. // Output:      Reference to new complex object
  359.  
  360. inline CoolComplex operator* (const CoolComplex& c1, const CoolComplex& c2) {
  361.   return CoolComplex (((c1.r * c2.r)-(c1.i * c2.i)),
  362.               ((c1.r * c2.i)+(c1.i * c2.r)));
  363. }
  364.  
  365.  
  366. // operator/ -- Overload the division operator for the CoolComplex class
  367. // Input:       Reference to complex object
  368. // Output:      Reference to new complex object
  369.  
  370. inline CoolComplex operator/ (const CoolComplex& c1, const CoolComplex& c2) {
  371.   CoolComplex result = c1;
  372.   result /= c2;
  373.   return result;
  374. }
  375.  
  376.  
  377. // operator+= -- Overload the addition/assign operator for the CoolComplex class
  378. // Input:        Reference to complex object
  379. // Output:       None
  380.  
  381. inline CoolComplex& CoolComplex::operator+= (const CoolComplex& c) {
  382.   this->r += c.r;                // Add real part
  383.   this->i += c.i;                // Add imaginary part
  384.   return *this;
  385. }
  386.  
  387.  
  388. // operator-= -- Overload the subtraction/assign operator for the CoolComplex class
  389. // Input:        Reference to complex object
  390. // Output:       None
  391.  
  392. inline CoolComplex& CoolComplex::operator-= (const CoolComplex& c) {
  393.   this->r -= c.r;                // Subtract real part
  394.   this->i -= c.i;                // Subtract imaginary part
  395.   return *this;
  396. }
  397.  
  398.  
  399. // operator*= -- Overload the multiplication/assign operator for CoolComplex class
  400. // Input:        Reference to complex object
  401. // Output:       None
  402.  
  403. inline CoolComplex& CoolComplex::operator*= (const CoolComplex& c) {
  404.   this->r = (this->r * c.r)-(this->i * c.i);    // Multiply real part
  405.   this->i = (this->r * c.i)+(this->i * c.r);    // Multiply imaginary part
  406.   return *this;
  407. }
  408.  
  409.  
  410. // sin --  Calculate the sine of a CoolComplex number
  411. // Input:  Reference to a complex
  412. // Output: Reference to a new complex whose value is the answer
  413.  
  414. inline CoolComplex CoolComplex::sin () const {
  415.   return CoolComplex (::sin (this->r), ::sin (this->i));
  416. }
  417.  
  418.  
  419. // cos --  Calculate the cosine of a Complex number
  420. // Input:  Reference to a complex
  421. // Output: Reference to a new complex whose value is the answer
  422.  
  423. inline CoolComplex CoolComplex::cos () const {
  424.   return CoolComplex (::cos (this->r), ::cos (this->i));
  425. }
  426.  
  427.  
  428. // tan --  Calculate the tangent of a CoolComplex number
  429. // Input:  Reference to a complex
  430. // Output: Reference to a new complex whose value is the answer
  431.  
  432. inline CoolComplex CoolComplex::tan () const {
  433.   return CoolComplex (::tan (this->r), ::tan (this->i));
  434. }
  435.  
  436.  
  437. // sinh -- Calculate the hyperbolic sine of a CoolComplex number
  438. // Input:  Reference to a complex
  439. // Output: Reference to a new complex whose value is the answer
  440.  
  441. inline CoolComplex CoolComplex::sinh () const {
  442.   return CoolComplex (::sinh (this->r), ::sinh (this->i));
  443. }
  444.  
  445.  
  446. // cosh -- Calculate the hyperbolic cosine of a CoolComplex number
  447. // Input:  Reference to a complex
  448. // Output: Reference to a new complex whose value is the answer
  449.  
  450. inline CoolComplex CoolComplex::cosh () const {
  451.   return CoolComplex (::cosh (this->r), ::cosh (this->i));
  452. }
  453.  
  454.  
  455. // tanh -- Calculate the hyperbolic tangent of a CoolComplex number
  456. // Input:  Reference to a complex
  457. // Output: Reference to a new complex whose value is the answer
  458.  
  459. inline CoolComplex CoolComplex::tanh () const {
  460.   return CoolComplex (::tanh (this->r), ::tanh (this->i));
  461. }
  462.  
  463. #endif COMPLEXH                    // End COMPLEXH
  464.